﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.IO;
using System.Reflection;
using Db4objects.Db4o;
using Db4objects.Db4o.Query;
using Db4objects.Db4o.Linq;

namespace States
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        readonly static string DBFileName =
            Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "States.db4o");

        public Window1()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(Window1_Loaded);
        }

        void Window1_Loaded(object sender, RoutedEventArgs e)
        {
        }

        private void HyperLink_ClearDataBase_RequestNavigate(object sender, RequestNavigateEventArgs e)
        {
            if (DataBase.ClearDataBase())
            {
                MessageBox.Show("Clear DB successfully!", "States", MessageBoxButton.OK, MessageBoxImage.Information);
            }
            else
            {
                MessageBox.Show(string.Format("Clear DB failed"), "States", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        #region Cau A.Import
        private void HyperLink_Import_RequestNavigate(object sender, RequestNavigateEventArgs e)
        {
            DoImport();
        }
        private void DoImport()
        {
            try
            {
                int nStateCount = 0;
                using (IObjectContainer db = Db4oEmbedded.OpenFile(DBFileName))
                {
                    Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog
                    {
                        RestoreDirectory = true,
                        DefaultExt = ".txt",
                        Filter = "Text documents (.txt)|*.txt"
                    };
                    bool? result = dlg.ShowDialog();
                    if (result == true)
                    {
                        string sFileName = dlg.FileName;
                        using (StreamReader DataFile = new StreamReader(sFileName))
                        {
                            string sLine = DataFile.ReadLine();
                            if (!string.IsNullOrEmpty(sLine))
                            {
                                if (int.TryParse(sLine, out nStateCount) && nStateCount > 0)
                                {
                                    for (int i = 0; i < nStateCount; i++)
                                    {
                                        State state = new State(DataFile.ReadLine());
                                        state.SetCities(DataFile.ReadLine());
                                        db.Store(state);
                                    }
                                }
                            }
                        }
                    }
                }

                MessageBox.Show(string.Format("{0} states imported.", nStateCount), "States", MessageBoxButton.OK, MessageBoxImage.Information);
            }
            catch (Exception ex)
            {
                MessageBox.Show(string.Format("Import states failed. \r\n{0}", ex.InnerException.Message), "States", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
        #endregion

        #region Cau B.1
        private void HyperLink_B1_RequestNavigate(object sender, RequestNavigateEventArgs e)
        {
            TabControl_Main.SelectedIndex = 0;
        }
        private void Button_Find_Click(object sender, RoutedEventArgs e)
        {
            string sResult = string.Empty;
            string sFirstLetters = TextBox_FirstLetters.Text;
            using (IObjectContainer db = Db4oEmbedded.OpenFile(DataBase.BDFile))
            {
                #region Use Native Query
                //IList<State> matchedStates = db.Query<State>(delegate(State state) 
                //{ 
                //    return state.StateCode.StartsWith(sFirstLetters); 
                //});
                //IList<State> matchedStates = db.Query<State>((s) =>
                //{
                //    return s.StateCode.StartsWith(sFirstLetters);
                //});
                #endregion

                #region Use LINQ
                //IEnumerable<State> matchedStates = from State state in db
                //                                   where state.StateCode.StartsWith(sFirstLetters)
                //                                   select state;
                #endregion

                #region Use SODA Query
                IQuery query = db.Query();
                query.Constrain(typeof(State));
                query.Descend("stateCode").Constrain(sFirstLetters).StartsWith(false);
                IObjectSet matchedStates = query.Execute();
                #endregion

                int nCount = 0;
                foreach (State state in matchedStates)
                {
                    sResult += (string.IsNullOrEmpty(sResult) ? string.Empty : "\r\n\r\n") + string.Format("{0}. {1}\r\n", (++nCount), state);
                    if (state.CapitalCity != null)
                        sResult += state.CapitalCity.ToString();
                }
            }

            if (string.IsNullOrEmpty(sResult))
                sResult = "No states matched !!!";

            TextBlock_Result.Text = sResult;
        }
        #endregion

        #region Cau B.2
        private void HyperLink_B2_RequestNavigate(object sender, RequestNavigateEventArgs e)
        {
            TabControl_Main.SelectedIndex = 1;

            string sResult = string.Empty;
            string sFirstLetters = TextBox_FirstLetters.Text;
            using (IObjectContainer db = Db4oEmbedded.OpenFile(DataBase.BDFile))
            {
                #region Use LINQ
                //IEnumerable<State> matchedStates = (from State state in db
                //                                    orderby state.Population descending
                //                                    select state).Take(5);
                #endregion

                #region Use SODA Query
                IQuery query = db.Query();
                query.Constrain(typeof(State));
                query.Descend("population").OrderDescending();
                IObjectSet matchedStates = query.Execute();
                #endregion

                int nCount = 0;
                foreach (State state in matchedStates)
                {
                    sResult += (string.IsNullOrEmpty(sResult) ? string.Empty : "\r\n\r\n") + string.Format("{0}. {1}\r\n", (++nCount), state);
                    if (nCount == 5)
                        break;
                }
            }

            if (string.IsNullOrEmpty(sResult))
                sResult = "No states matched !!!";

            TextBlock_Result2.Text = sResult;

        }
        #endregion

        #region Cau B.3
        private void HyperLink_B3_RequestNavigate(object sender, RequestNavigateEventArgs e)
        {
            TabControl_Main.SelectedIndex = 2;
        }
        private void Button_Find3_Click(object sender, RoutedEventArgs e)
        {
            string sResult = string.Empty;
            string sStateName = TextBox_StateName.Text;
            using (IObjectContainer db = Db4oEmbedded.OpenFile(DataBase.BDFile))
            {
                #region Use Native Query
                IList<State> matchedStates = db.Query<State>(delegate(State state)
                {
                    return state.StateName.Contains(sStateName);
                });
                //IList<State> matchedStates = db.Query<State>((s) =>
                //{
                //    return s.StateName.Contains(sStateName);
                //});
                #endregion

                #region Use LINQ
                //IEnumerable<State> matchedStates = from State state in db
                //                                   where state.StateName.Contains(sStateName)
                //                                   select state;
                #endregion

                #region Use SODA Query
                //IQuery query = db.Query();
                //query.Constrain(typeof(State));
                //query.Descend("stateName").Constrain(sStateName).Contains();
                //IObjectSet matchedStates = query.Execute();
                #endregion

                int nCount = 0;
                foreach (State state in matchedStates)
                {
                    sResult += (string.IsNullOrEmpty(sResult) ? string.Empty : "\r\n\r\n") + string.Format("{0}. {1}\r\n", (++nCount), state);

                    if (state.CapitalCity != null)
                        sResult += state.CapitalCity.ToString() + "\r\n";

                    foreach (var city in state.Cities)
                    {
                        sResult += city.ToString() + " ";
                    }
                }
            }

            if (string.IsNullOrEmpty(sResult))
                sResult = "No states matched !!!";

            TextBlock_Result3.Text = sResult;
        }
        #endregion

        #region Cau B.4
        private void HyperLink_B4_RequestNavigate(object sender, RequestNavigateEventArgs e)
        {
            TabControl_Main.SelectedIndex = 3;

            string sResult = string.Empty;
            using (IObjectContainer db = Db4oEmbedded.OpenFile(DataBase.BDFile))
            {
               
                char c = 'A';
                int i = 0;
                while (true)
                {
                    string s = c.ToString();

                    #region Use LINQ
                    //int count = (from State state in db
                    //             where state.StateName.StartsWith(s)
                    //             select state).Count();
                    #endregion

                    #region Use SODA Query
                    IQuery query = db.Query();
                    query.Constrain(typeof(State));
                    query.Descend("stateName").Constrain(s).StartsWith(false);
                    IObjectSet matchedStates = query.Execute();
                    int count = matchedStates.Count;
                    #endregion

                    sResult += (string.IsNullOrEmpty(sResult) ? string.Empty : ((i % 4) == 0 ? "\r\n\r\n" : "       ")) + string.Format("{0} : {1}", s, count);
                    if (s == "Z")
                        break;

                    i++;
                    c++;
                }

                TextBlock_Result4.Text = sResult;
            }

            if (string.IsNullOrEmpty(sResult))
                sResult = "No states matched !!!";

            TextBlock_Result2.Text = sResult;

        }
        #endregion

        #region Cau B.5
        private void HyperLink_B5_RequestNavigate(object sender, RequestNavigateEventArgs e)
        {
            if (MessageBox.Show("Are you sure you want to quit?", "States", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
                this.Close();
        }
        #endregion
    }
}
